/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.zfes.snowy.auth.shiro.cas;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.zfes.snowy.auth.AuthConsts;
import org.zfes.snowy.auth.shiro.filter.authc.SnowyAccessControlFilter;
import org.zfes.snowy.auth.shiro.handlers.IAuthecFailureHandler;
import org.zfes.snowy.auth.shiro.handlers.IAuthecSuccessHandler;
import org.zfes.snowy.auth.shiro.suser.SessionUser;
import org.zfes.snowy.auth.shiro.suser.SessionUserManager;
import org.zfes.snowy.core.util.AppCtxUtil;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;


public class SnowyCasAuthFilter extends SnowyAccessControlFilter {
    
    private static final String TICKET_PARAMETER = "ticket";
    
    protected IAuthecSuccessHandler  authecSuccessHandler;
    protected IAuthecFailureHandler  authecFailureHandler;
    
    
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        AuthenticationToken token = createToken(request, response);
        if (token == null) {
            String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken must be created in order to execute a login attempt.";
            throw new IllegalStateException(msg);
        }
        try {
            Subject subject = getSubject(request, response);
            Session session=subject.getSession();
            subject.login(token);
            
            //登录后，初始化session_user信息 
        	SessionUserManager sessionUserManager=AppCtxUtil.getBean("sessionUserManagerImpl");
        	Optional<SessionUser> sessionUserOp =sessionUserManager.loadSessionUser((String)subject.getPrincipal());
			if(!sessionUserOp.isPresent()){
				throw new AuthenticationException("未正确初始化用户信息");
			}
			SessionUser sessionUser=sessionUserOp.get();
			sessionUser.setAuthLevel(2);
			session.setAttribute(AuthConsts.SESSION.SESSION_USER_KEY,sessionUser);
            authecSuccessHandler.onAuthenticationSuccess(WebUtils.toHttp(request), WebUtils.toHttp(response), subject,false);
        } catch (AuthenticationException e) {
        	authecFailureHandler.onAuthenticationFailure(WebUtils.toHttp(request), WebUtils.toHttp(response), e);
        }
        return false;
    }
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String ticket = httpRequest.getParameter(TICKET_PARAMETER);
        return new SnowyCasToken(ticket);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        return executeLogin(request, response);
    }
    
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        return false;
    }
	public IAuthecSuccessHandler getAuthecSuccessHandler() {
		return authecSuccessHandler;
	}
	public void setAuthecSuccessHandler(IAuthecSuccessHandler authecSuccessHandler) {
		this.authecSuccessHandler = authecSuccessHandler;
	}
	public IAuthecFailureHandler getAuthecFailureHandler() {
		return authecFailureHandler;
	}
	public void setAuthecFailureHandler(IAuthecFailureHandler authecFailureHandler) {
		this.authecFailureHandler = authecFailureHandler;
	}
    
}
